#include "../Mocker.h"
#include "StackWalker.h"

extern "C" bool IsMockerAlive()
{
	return MockItNow::Mocker::IsAlive();
}

extern "C" bool ThunkShouldStubFunction(size_t callingFunctionAddress, size_t targetPointer)
{
	using namespace MockItNow;
	return (Mocker::IsAlive() && Mocker::Instance().ShouldStubFunction(callingFunctionAddress, targetPointer));
}

extern "C"  size_t ThunkSetCurrentFunctionAndGetFunctionJumpAddress(size_t callingFunctionAddress)
{
	using namespace MockItNow;
	Mocker::Instance().SetCurrentFunctionAddress(callingFunctionAddress);
	return Mocker::Instance().GetFunctionJumpAddress();
}

struct cFunctionContext
{
	//! Function address
	size_t address;

	//! Value of RSP at the beginning of the function - before any stack allocation.
	size_t RSP;
};

/*! Return the function context of the calling function. The function context is described in the
    cFunctionContext structure.

	For example, consider the following call stack:

		FunctionWeAreInterestedIn()
		....AnotherFunction()
		.......GetCallingFunctionContext()

    In this case GetCallingFunctionContext will return the function context of FunctionWeAreInterestedIn.
*/
extern "C" cFunctionContext GetCallingFunctionContext()
{
	cFunctionContext context;
	context.address = 0;
	context.RSP		= 0;

	// We need three entries in the stack trace.
	// FunctionWeWantTheContextFor()
	//	....CallingFunction()
    //		.......GetCallingFunctionContext()
	const int  stackDepth = 3;
	StackTrace stackTrace;

	if(WalkStack(stackDepth, stackTrace) == stackDepth)
	{
		context.address = stackTrace[stackDepth-1].functionAddress;
		context.RSP     = stackTrace[stackDepth-1].rspBeforePrologue;
	}

	return context;
}
